interface PeekableIterableIterator<T> extends IterableIterator<T> {
    peek: () => IteratorResult<T>
}

export function makePeekable<T>(iterable: Iterable<T>): PeekableIterableIterator<T> {
    const iterator = iterable[Symbol.iterator]()
    let peeked: IteratorResult<T> | undefined

    return {
        [Symbol.iterator](this: IterableIterator<T>) {
            return this
        },
        next() {
            if (peeked) {
                const current = peeked
                peeked = undefined
                return current
            }

            return iterator.next()
        },
        peek() {
            if (peeked)
                return peeked

            return peeked = iterator.next()
        },
    }
}
